#include <stdlib.h>
#include <time.h>
#include "XrdDMSimulator.hh"
#include "XrdDownloadManager.hh"

XrdDMSimulator::XrdDMSimulator():fNumSites(0)
{
}

XrdDMSimulator::~XrdDMSimulator()
{

}

void XrdDMSimulator::GenerateFileCatalog(int numFiles,int sitePerFile)
{
  fFileCatalog.Generate(this,numFiles,sitePerFile);
}


void XrdDMSimulator::Simulate(int numEvents)
{

  fDownloadManager.SetSimulator(this);
//   fDownloadManager.SetDebug(10);
  // opening files
  XrdDMSimSiteInfo *site;
  XrdDMSimFileInfo *file;

  int numOk=0;
  int numFailed=0;
  int numTries=0;


  int fileIndex;
  int randomOIndexSite;
  int downloadResult;
  string xrdFullPath;
  for (int i=0;i<numEvents;i++) {
    cout << "======= Processing Event # " << i << " ======="<< endl;
    fileIndex = (int)(double)rand()/RAND_MAX*fFileCatalog.GetNumerOfFiles();
    fDownloadManager.Reset();

    // loop over possible sites
    for (int j=0;j<fFileCatalog.GetNumerOfSites();j++) {
      randomOIndexSite = (int)(double)rand()/RAND_MAX*fFileCatalog.GetNumerOfSites();
      site = fFileCatalog.GetSite(j,fileIndex);
      file = fFileCatalog.GetFile(j,fileIndex);
      if (site->IsOk()) {
//         AddFile(&dm,site,file);
        xrdFullPath = "root://";
        xrdFullPath.append(site->GetName());
        xrdFullPath.append(":");
        xrdFullPath.append(site->GetPort());
        xrdFullPath.append("/");
        xrdFullPath.append(file->GetName());

        fDownloadManager.AddFileToDownload(xrdFullPath,fFileCatalog.IsFileStaged(j,fileIndex));
      }
    }

    downloadResult = fDownloadManager.DownloadFile();
    if (downloadResult==1) {
      numTries += downloadResult;
      numOk++;
    } else {
      numFailed++;
    }

    cout << "=========== End of Event # " << i << " ======="<< endl;
  }

  cout << "Number of OK : " << numOk << endl;
  cout << "Number of Failed : " << numFailed << endl;
  cout << "Number of Tries : " << numTries << endl;

}

XrdDMSimSiteInfo *XrdDMSimulator::AddSite(string name,int minSpeed, int maxSpeed, int percentFailure)
{
  fSites[fNumSites].SetName(name);
  fSites[fNumSites].SetSiteInfo(minSpeed,maxSpeed,percentFailure);
  fNumSites++;
  return &fSites[fNumSites-1];
}


XrdDMSimSiteInfo* XrdDMSimulator::GetSiteByName(string name)
{
  size_t found;
  for (int i=0;i<fNumSites;i++) {
//     fSites[i].Print();
    found = name.find(fSites[i].GetName());
    if (found!=string::npos)
      return GetSite(i);
  }

  return 0;
}


int XrdDMSimulator::GetSiteRandomSpeed(string siteName)
{
  XrdDMSimSiteInfo *site = GetSiteByName(siteName);
  int diff = site->GetSpeedMax() - site->GetSpeedMin();
  int randomSpeed = ((int)((double)rand()/RAND_MAX*diff))+site->GetSpeedMin();
//   cout << "Random Speed is "<<randomSpeed << endl;
  return randomSpeed;
}


void XrdDMSimulator::Print()
{
  for (int i=0;i<fNumSites;i++)
    fSites[i].Print();
  fFileCatalog.Print();
}

